using System;
using System.Collections.Generic;
using System.Data;
using System.Configuration;
using System.Collections;
using System.IO;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;

using Swaf;
using Swaf.BizObj;
using Swaf.Gui;
using Swaf.Gui.AspNet2;
using Syrinx.Gui.AspNet.Nitobi2;

	public partial class AjaxRequestHandler : System.Web.UI.Page, INitobiPage
	{
		protected ServerControlLocalizer m_localizer;
		protected Control m_pageForm = null;
		protected BizProcCoordinator m_bpc = null;
		protected XmlDocument m_browserStateDoc = null;
		protected string m_pageRequestId = "";
		protected ActiveWidget m_eventWidget = null;

		protected override void OnPreInit(EventArgs e)
		{
			base.OnPreInit(e);
			//Setting up the ajax response theme allows controls that were created dynamically to be properly
			//setup with the current theme.
			if (CurrentUser != null && CurrentUser.containsField("settings.themeName"))
			{
				string themeName = CurrentUser.get("settings.themeName") as string;
				if (!Cmn.IsEmpty(themeName))
					Page.Theme = themeName;
			}

		}
		public IBizObj CurrentUser { get { return App.securityMgr.currentPrincipal.additionalInfo as IBizObj; } }

		protected override void OnInitComplete(EventArgs e)
		{
			base.OnInitComplete(e);
			m_pageForm = FindControl("form1");

			Response.ContentType = "text/xml";
			Response.AddHeader("Pragma", "no-cache");
			Response.AddHeader("Expires", "Tue, 01 Jan 1980 1:00:00 GMT");
			m_pageRequestId = Request["pi"];
			string requestType = Request["RequestType"];

			StreamReader rdr = new StreamReader(Request.InputStream);
			string xml = rdr.ReadToEnd();
			rdr.Close();

			try
			{
				string ajaxOutLoc = (string)App.appData.get("AjaxDebugOutput");
				if (!Cmn.IsEmpty(ajaxOutLoc))
					File.WriteAllText(Cmn.pathCombine(ajaxOutLoc, "IN-" + DateTime.Now.ToString("yyMMddHHmmssF") + ".xml"), xml);
			}
			catch (Exception) { }

			m_browserStateDoc = new XmlDocument();
			m_browserStateDoc.LoadXml(xml);

			//m_eventBizProc = BPC.getActiveBizProc(m_browserStateDoc.DocumentElement.GetAttribute("bizProcId"));
		}

		protected override void OnLoadComplete(EventArgs e)
		{
			base.OnLoadComplete(e);

			string actionWidgetId = m_browserStateDoc.DocumentElement.GetAttribute("id");
			m_eventWidget = BPC.getActiveWidget(actionWidgetId);
			if (m_eventWidget.Widget is INitobiClientControl)
			{
				INitobiClientControl ctl = m_eventWidget.Widget as INitobiClientControl;
				((INitobiClientControl)m_eventWidget.Widget).processAjaxEvent(m_browserStateDoc.DocumentElement);
			}

		}

		protected override void OnPreRender(EventArgs e)
		{
			//Because going through the initial list of active bizprocs could add more to the list, we must actually
			//make a seperate list and go through that one first and force show and then again to catch
			//the extra ones that didnt show yet.
			List<ActiveBizProc> bpcs = new List<ActiveBizProc>(BPC.ActiveBizProcs.Count);
			cloneListAndShowData(bpcs);
			cloneListAndShowData(bpcs);
			cloneListAndShowData(bpcs);
			cloneListAndShowData(bpcs);

			//foreach (ActiveBizProc b in BPC.ActiveBizProcs.Values)
			//    bpcs.Add(b);
			//foreach (ActiveBizProc b in bpcs)
			//    b.BizProc.showData(ForceLevel.mustShowGetAllDataIfNeeded);

			//foreach (ActiveBizProc b in BPC.ActiveBizProcs.Values)
			//    if (!bpcs.Contains(b))
			//        b.BizProc.showData(ForceLevel.mustShowGetAllDataIfNeeded);

			//foreach (BizProcOfflineState offline in BPC.PageState.BizProcStates.Values)
			//    foreach (ParentBizProcInfo pinfo in offline.ParentBizProcs.Values)
			//        if (pinfo.ParentId == "_all")
			//        {
			//            ActiveBizProc b = BPC.getActiveBizProc(offline.Id);
			//            b.BizProc.showData(ForceLevel.mustShowGetAllDataIfNeeded);
			//        }
			base.OnPreRender(e);
		}

		protected void cloneListAndShowData(List<ActiveBizProc> bpcs)
		{
			//Because going through the initial list of active bizprocs could add more to the list, we must actually
			//make a seperate list and go through that one first and force show and then again to catch
			//the extra ones that didnt show yet.
			List<ActiveBizProc> cloned = new List<ActiveBizProc>(BPC.ActiveBizProcs.Count);
			foreach (ActiveBizProc b in BPC.ActiveBizProcs.Values)
				cloned.Add(b);
			foreach (ActiveBizProc b in cloned)
				if (!bpcs.Contains(b) && b.BizProc.Id != "_all")
				{
					bpcs.Add(b);
					b.BizProc.showData(ForceLevel.mustShowGetAllDataIfNeeded);
				}
		}


		protected override void Render(System.Web.UI.HtmlTextWriter writer)
		{
			//Create the response back to the browser client, using the states of the control
			XmlDocument resp = new XmlDocument();
			resp.LoadXml("<AjaxResponse />");
			XmlElement states = resp.CreateElement("ControlStates");
			resp.DocumentElement.AppendChild(states);

			m_localizer = new ServerControlLocalizer(BPC.PageState.PageId);
			if (m_localizer != null && m_localizer.ShouldTrackPageFields)
			{
				localizeControls(Controls);
				if (m_localizer.UiViewLocalizationInfo != null && m_localizer.UiViewLocalizationInfo.Count > 0)
				{
					IBizObj uiView = m_localizer.UiViewLocalizationInfo[0];
					IResults rc = App.ruleMgr.execute("addApplicationView", uiView);
				}
			}


			foreach (ActiveWidget widget in BPC.ActiveWidgets.Values)
				setupWidgetClientXml(widget, states, true, null);

			string pageHtml = getPageHtml();
			
			foreach (ActiveWidget widget in BPC.ActiveWidgets.Values)
				setupWidgetClientXml(widget, states, false, pageHtml);
			
			string xml = resp.DocumentElement.OuterXml;
			try
			{
				string ajaxOutLoc = (string)App.appData.get("AjaxDebugOutput");
				if (!Cmn.IsEmpty(ajaxOutLoc))
					File.WriteAllText(Cmn.pathCombine(ajaxOutLoc, "Out-" + DateTime.Now.ToString("yyMMddHHmmssF") + ".xml"), xml);
			}
			catch (Exception) { }

			Context.Response.Write(xml);
			Context.Response.End();

		}

		private void localizeControls(ControlCollection controls)
		{
			foreach (Control ctl in controls)
				if (ctl is MasterPage || ctl is ContentPlaceHolder || ctl is HtmlForm || ctl is Swaf.Gui.AspNet2.UserControl)
					localizeControls(ctl.Controls);
				else if (!(ctl is LiteralControl) && ctl.ID != null)
					m_localizer.localizeControl(ctl, this, "");
		}

		protected void setupWidgetClientXml(ActiveWidget widget, XmlElement states, bool preRender, string pageHtml)
		{
			if (widget.Widget is INitobiClientControl && !widget.CreatedFromPage && ((Control)widget.Widget).Page != null &&
				((!preRender && ((INitobiClientControl)widget.Widget).NeedToGenerateHtmlWithServerControls) ||
				(preRender && !((INitobiClientControl)widget.Widget).NeedToGenerateHtmlWithServerControls)))
			{
				INitobiClientControl ctl = widget.Widget as INitobiClientControl;
				XmlElement stateEl = states.OwnerDocument.CreateElement("State");
				stateEl.SetAttribute("id", ctl.WidgetId);
				ctl.getState(stateEl, pageHtml);
				states.AppendChild(stateEl);
			}
		}

		protected string getPageHtml()
		{
			string pageHtml = null;
			bool needToGen = false;
			foreach (ActiveWidget widget in BPC.ActiveWidgets.Values)
				if (!(widget.Widget is INitobiClientControl && ((INitobiClientControl)widget.Widget).NeedToGenerateHtmlWithServerControls))
				{
				//	m_pageForm.Controls.Remove((Control)widget.Widget);
				}
				else
					needToGen = true;
			if (needToGen)
			{
				StringWriter swr = new StringWriter();
				HtmlTextWriter html = new HtmlTextWriter(swr);

				//base.Render(html);
				Form.RenderControl(html);
				pageHtml = swr.ToString();
				return pageHtml;
			}
			return pageHtml;
		}

		protected string PageStateSessionId
		{
			get
			{
				if (m_pageRequestId.EndsWith("popup_aspx"))
					return "PopupPageState";
				else
					return "ActivePageState";
			}
		}

		public BizProcCoordinator BPC
		{
			get
			{
				if (m_bpc == null)
				{
					ViewOfflineState pageState = PageStateManager.getState(m_pageRequestId, false);
					if (pageState == null)
						throw new BaseException(string.Format("No page state found in session using key :{0}:", m_pageRequestId));
					m_bpc = new BizProcCoordinator(this, pageState);
				}
				return m_bpc;
			}
			set
			{
				m_bpc = value;
			}
		}
		protected Swaf.IApplication App { get { return Swaf.Application.currentApp; } }

		public void BizProcCreated(ActiveBizProc bizProc)
		{
		}

		public void WidgetCreated(ActiveWidget widget)
		{
			if (widget.Widget is INitobiClientControl)
			{
				INitobiClientControl ctl = widget.Widget as INitobiClientControl;
				ctl.CreateOnLoad = false;
			}
			if (((Control)widget.Widget).Page == null)
				m_pageForm.Controls.Add(widget.Widget as Control);
			if (widget.Widget is INitobiClientControl)
			{
				INitobiClientControl ctl = widget.Widget as INitobiClientControl;
				XmlElement stateEl = m_browserStateDoc.DocumentElement.SelectSingleNode("//ControlStates/State[@id = '" + ctl.WidgetId + "']") as XmlElement;
				if (stateEl != null)
					ctl.setState(stateEl);
			}
		}
		public void gotoView(string name) { }
		public String ViewName { get { return m_pageRequestId; } }
	}
